/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.ui.util;

import java.awt.Container;
import java.io.File;
import java.util.Map;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import org.apache.log4j.Logger;

import who.tmap.bo.Attrs;
import who.tmap.bo.BizObject;
import who.tmap.bo.BizObjects;
import who.tmap.bo.ThematicMap;
import who.tmap.bo.cd.CDTypes;
import who.tmap.bo.cd.CartographicDisplay;
import who.tmap.bo.cd.impl.CartographicDisplayFactory;
import who.tmap.bo.impl.BizObjectFactory;
import who.tmap.common.TMapException;
import who.tmap.dao.TMapDAOException;
import who.tmap.dao.ThematicMapDAO;
import who.tmap.dao.impl.DAOFactory;
import who.tmap.toolkit.MappingToolKit;
import who.tmap.toolkit.impl.CartographicDisplayHelper;
import who.tmap.toolkit.shape.MapShape;
import who.tmap.ui.JDialogImageOutputSize;
import who.tmap.ui.JDialogThematicMapProperties;
import who.tmap.ui.JFrameThematicMap;
import who.tmap.ui.undo.UndoManager;
import who.tmap.ui.undo.impl.UndoManagerImpl;

public class ThematicMapUIHelper extends BaseUIHelper {

    private static Logger logger = Logger.getLogger(ThematicMapUIHelper.class);
    
    private static UndoManager undoManager =UndoManagerImpl.getInstance();

    private JFrameThematicMap jFrameThematicMap;
    
    public ThematicMapUIHelper( JFrameThematicMap jFrameThematicMap ) {
    	this.jFrameThematicMap =jFrameThematicMap;
    }
    
    public boolean saveNeeded( ThematicMap thematicMap ) {
    	return ( thematicMap != null && 
    			( thematicMap.isDirty()
    			|| ( thematicMap.getAnnotations() != null && ( thematicMap.getAnnotations().isDirty() || jFrameThematicMap.jFrameAnnotations.isDirty() ) )
    			|| ( thematicMap.getData() != null && ( thematicMap.getData().isDirty() ||  ((DataTableDataModel)jFrameThematicMap.jFrameData.getJTable().getModel()).isDirty() ) )
    			|| ( thematicMap.getBaseMap() != null && thematicMap.getBaseMap().isDirty() ) 
    			|| ( thematicMap.getCartographicDisplay() != null && ( thematicMap.getCartographicDisplay().isDirty() || jFrameThematicMap.jFrameCartographicDisplay.isDirty() ) ) 
    
    	) );	
    }
    
    public int saveNeededUI( Container container, ThematicMap thematicMap ) {
    	
        int n =JOptionPane.NO_OPTION;
        
        if ( saveNeeded( thematicMap ) ) {
        	n =JOptionPane.showConfirmDialog( container,
                "The current thematic map needs to be saved. Do you want to save it?",
                "Save Thematic Map",
                JOptionPane.YES_NO_CANCEL_OPTION);
        	
        	if ( n == JOptionPane.YES_OPTION ){
    			try {
					thematicMap.setBaseMap( jFrameThematicMap.jFrameMap.getMappingToolKit().retrieveBaseMap() );

					save( container, thematicMap
						, jFrameThematicMap.jFrameMap.getJPanel().getWidth()
						, jFrameThematicMap.jFrameMap.getJPanel().getHeight() );
				} catch (TMapException e) {
					miscUIHelper.displayErrorMessage( container, e );
				}
        	}
        }
        
        return n;
    }
    
    private void save( ThematicMap thematicMap ) throws TMapDAOException {
    	jFrameThematicMap.jFrameAnnotations.retrieveAnnotations();
    	
    	ThematicMapDAO thematicMapDAO = (ThematicMapDAO)DAOFactory.getInstance().get( DAOFactory.THEMATIC_MAP );
    	
    	thematicMap.setLinkedFile( thematicMap.getFile().getAbsolutePath().toLowerCase()
    								.endsWith(FileChooserFilter.THEMATIC_MAP_LINKED_EXT) );	
    	    	
    	thematicMapDAO.save( thematicMap.getFile().getAbsolutePath(), thematicMap );
		thematicMap.setDirty(false);
		
		jFrameThematicMap.jFrameData.setDirty( false );		
		jFrameThematicMap.jFrameAnnotations.setDirty( false );
		jFrameThematicMap.jFrameCartographicDisplay.setDirty( false );		
    }
    
	public File save( Container container, BizObject bizObject, int width, int height ) {
		ThematicMap thematicMap =(ThematicMap)bizObject;
		
		try {
	        if ( thematicMap.getFile() != null ) {
        		if ( thematicMap.isLinkedFile() ) {
					JDialogThematicMapProperties dlg 
						=new JDialogThematicMapProperties( 
								JOptionPane.getFrameForComponent( container )
							  , true
							  , thematicMap );
					dlg.setVisible( true );
					dlg.dispose();
        		}	        	
	            save( thematicMap );
	            return thematicMap.getFile();
	        } else {
	        	return saveAs( container, thematicMap, width, height );
	        }		
        } catch (TMapDAOException e) {
            miscUIHelper.displayErrorMessage( container, e );
        }        
        
        return null;
	}
	
	public File saveAs( Container container, BizObject bizObject, int width, int height ) {
	    File file =null;
	    ThematicMap thematicMap =(ThematicMap)bizObject;
		JFileChooser fileChooser = new JFileChooser();
		
		FileChooserFilter jpgFcf =new FileChooserFilter( FileChooserFilter.JPG_EXT );
		FileChooserFilter pngFcf =new FileChooserFilter( FileChooserFilter.PNG_EXT );
		FileChooserFilter tmaFcf =new FileChooserFilter( FileChooserFilter.THEMATIC_MAP_EXT );	
		FileChooserFilter tmlFcf =new FileChooserFilter( FileChooserFilter.THEMATIC_MAP_LINKED_EXT );	
		
		fileChooser.addChoosableFileFilter( jpgFcf );
		fileChooser.addChoosableFileFilter( tmaFcf );	
		fileChooser.addChoosableFileFilter( tmlFcf );			
		fileChooser.addChoosableFileFilter( pngFcf );
		
		fileChooser.setFileFilter( tmaFcf );
		fileChooser.setCurrentDirectory( getTmaDir( container ) );
		fileChooser.setSelectedFile( new File( "*" + FileChooserFilter.THEMATIC_MAP_EXT ));
		
		// Save file dialog.
		int retVal =fileChooser.showSaveDialog(container);
		
		if ( retVal == JFileChooser.APPROVE_OPTION ) {
			file =fileChooser.getSelectedFile();
			
			setTmaDir( fileChooser.getSelectedFile().getParentFile() );
	
		    logger.debug( "selectedFile=[" + file + "]" );

	        if ( file.exists() ) {

	            int n =JOptionPane.showConfirmDialog( container,
	                    "This file already exists. Do you want to erase it?",
	                    "Save Thematic Map",
	                    JOptionPane.YES_NO_OPTION);
	            if ( n == JOptionPane.NO_OPTION ) {
	                file =null;
	            }
	        }
	        
	        if ( file != null ) {
	        	
	        	FileFilter fcf =fileChooser.getFileFilter();
	        	
	        	if ( fcf.equals( (FileFilter)tmaFcf )
	        			|| file.getAbsolutePath().endsWith( FileChooserFilter.THEMATIC_MAP_EXT ) 
	        			|| file.getAbsolutePath().endsWith( FileChooserFilter.THEMATIC_MAP_LINKED_EXT ) ) {	        	
		        	thematicMap.setFile( file );
	            	try {
	            		thematicMap.setLinkedFile( file.getAbsolutePath().endsWith( FileChooserFilter.THEMATIC_MAP_LINKED_EXT ) );
	            		if ( thematicMap.isLinkedFile() ) {
							JDialogThematicMapProperties dlg 
								=new JDialogThematicMapProperties( 
										JOptionPane.getFrameForComponent( container )
									  , true, thematicMap );
							dlg.setVisible( true );
							dlg.dispose();
							
	            		}
	            		
						save( thematicMap );

					} catch (TMapDAOException e) {
			            miscUIHelper.displayErrorMessage( container, e );
					}
				
	        	} else {
	        		try {
	        			JDialogImageOutputSize dlg =new JDialogImageOutputSize( null, width, height );
	        			dlg.setModal( true );
	        			dlg.setVisible( true );
	        			
	        			int imgWidth =dlg.getImgWidth();
	        			int imgHeight =dlg.getImgHeight();
	        			boolean okPressed =dlg.isOkPressed();
	        			boolean removeBlankEdges =dlg.isRemoveBlankEdges();
	        			
	        			dlg.dispose();
	        			
	        			if ( okPressed ) {
	        				jFrameThematicMap.jFrameMap.getMappingToolKit().fitToWindow();
	        				jFrameThematicMap.jFrameMap.resetZoom();
	        				boolean success =jFrameThematicMap.jFrameMap.getMappingToolKit()
	        									.saveThematicMapAsBitmap( file
	        									, ((FileChooserFilter)fcf).getExtension()
												, imgWidth, imgHeight, removeBlankEdges );
	        			}
	        			
					} catch (Exception e) {
			            miscUIHelper.displayErrorMessage( container, e );
					}
					
					file =null;
	        	}
	        }

		}
		
		return file;
	}	    
	
	/**
	 * 
	 */
	public BizObject open( Container container, ThematicMap currentThematicMap )  {
		ThematicMap thematicMap =null;
		JFileChooser fileChooser = new JFileChooser();
		FileFilter tmaFileFilter =new FileChooserFilter( FileChooserFilter.THEMATIC_MAP_EXT );
		fileChooser.addChoosableFileFilter( tmaFileFilter );		
		fileChooser.addChoosableFileFilter( new FileChooserFilter( FileChooserFilter.THEMATIC_MAP_LINKED_EXT ) );		

		fileChooser.setFileFilter( tmaFileFilter );
		fileChooser.setCurrentDirectory( getTmaDir( container ) );
		
		// Open file dialog.
		int retVal =fileChooser.showOpenDialog(	container );
		
		if ( retVal == JFileChooser.APPROVE_OPTION ) {		
			
			if ( saveNeededUI( container, currentThematicMap ) == JOptionPane.CANCEL_OPTION ) {
				return currentThematicMap;
			}
		
			File file =fileChooser.getSelectedFile();
			
			setTmaDir( file.getParentFile() );
			
			try {
				resetUI();
		    	ThematicMapDAO thematicMapDAO = (ThematicMapDAO)DAOFactory.getInstance().get( DAOFactory.THEMATIC_MAP );
		    	thematicMap =(ThematicMap)thematicMapDAO.load( file.getAbsolutePath() );
			} catch( TMapException e1 ) {
				miscUIHelper.displayErrorMessage( container, e1 );
			}
		    
		}
		
	    return thematicMap;
	}    
	
	public BizObject newInstance( Container container ) {
	    ThematicMap thematicMap =null;
        try {
        	thematicMap = (ThematicMap)BizObjectFactory.getInstance().get( BizObjectFactory.THEMATIC_MAP );
        } catch (TMapException e) {
            miscUIHelper.displayErrorMessage( container, e );
        }
        
        return thematicMap;
	}	
	
	public int newThematicMap( Container container ) {
		return newThematicMap( container, true );
	}
	
	private void resetUI() {
		undoManager.clear();
		
		jFrameThematicMap.jFrameMap.getMappingToolKit().reset();
		jFrameThematicMap.jFrameMap.setGeoBoxNotInitializedAlreadyWarned( false );
		jFrameThematicMap.jFrameMap.resetUI();
		jFrameThematicMap.resetEditMode();
	}
	
	public int newThematicMap( Container container, boolean checkSaveNeeded ) {
		if ( checkSaveNeeded && saveNeededUI( container, jFrameThematicMap.getThematicMap() ) == JOptionPane.CANCEL_OPTION ) {
			return JOptionPane.CANCEL_OPTION;
		}
		
		resetUI();

		ThematicMap thematicMap =(ThematicMap)newInstance( container );
		jFrameThematicMap.setThematicMap( thematicMap );
		jFrameThematicMap.jFrameMap.getMappingToolKit().setThematicMap( thematicMap );

		jFrameThematicMap.jFrameData.setThematicMap( thematicMap );	
		Attrs attrs =null;
		try {
			attrs =(Attrs)BizObjectFactory.getInstance().get( BizObjects.ATTRS );
		} catch (TMapException e) {
		}
		thematicMap.setData( attrs );
	    DataTableDataModel dataModel =(DataTableDataModel)jFrameThematicMap.jFrameData.getJTable().getModel();
	    dataModel.setAttrs( thematicMap.getData() );
		
		CartographicDisplay cd =null;
		try {
			cd = CartographicDisplayFactory.getInstance().get( CDTypes.DEFAULT_CD );
		} catch (TMapException e1) {
			logger.error( e1 );
		}
		thematicMap.setCartographicDisplay( cd );
		jFrameThematicMap.jFrameCartographicDisplay.setThematicMap( thematicMap );
		jFrameThematicMap.jFrameCartographicDisplay.refreshData();	
		
		jFrameThematicMap.jFrameAnnotations.setThematicMap( thematicMap );
		jFrameThematicMap.jFrameAnnotations.refreshData();
		//jFrameThematicMap.jFrameAnnotations.setDirty( false );
		
		setThematicMapName( "" );	
		
		return JOptionPane.OK_OPTION;
	}
	
	public void applyThematicMap( Container container ) {
		if ( jFrameThematicMap.getThematicMap().getBaseMap() == null ) {
			return;
		}
		
		undoManager.clear();
		
		MappingToolKit mtk =jFrameThematicMap.jFrameMap.getMappingToolKit();
		
		int dbasePolygonIdx =mtk.getDbaseJoinIdx();
		mtk.reset();		
		mtk.setDbaseJoinIdx( dbasePolygonIdx );
		
		ThematicMap thematicMap =jFrameThematicMap.getThematicMap();
		mtk.setThematicMap( thematicMap );
		jFrameThematicMap.jFrameMap.setBaseMap( thematicMap.getBaseMap() );
		
		mtk.setMinX( thematicMap.getBaseMap().getMinX() );
		mtk.setMinY( thematicMap.getBaseMap().getMinY() );                    
		mtk.setMaxX( thematicMap.getBaseMap().getMaxX() );
		mtk.setMaxY( thematicMap.getBaseMap().getMaxY() );                    
        
		try {
			mtk.addShapes( thematicMap.getBaseMap().getShapes() );
		} catch (TMapException e1) {
			miscUIHelper.displayErrorMessage( container, e1 );
		}
        
        // Process display factor based on shape file import
		mtk.processMapFactor(); 					
	    
	    DataTableDataModel dataModel =(DataTableDataModel)jFrameThematicMap.jFrameData.getJTable().getModel();
	    dataModel.setAttrs( thematicMap.getData() );
	    jFrameThematicMap.jFrameData.setThematicMap( thematicMap );
	    
	    jFrameThematicMap.jFrameCartographicDisplay.setThematicMap( thematicMap );
	    jFrameThematicMap.jFrameCartographicDisplay.refreshData();
		
		CartographicDisplay cd =thematicMap.getCartographicDisplay();
	    
		Map<MapShape, Object> data =null;
		try {
			data = new CartographicDisplayHelper().assignValues( 
							  jFrameThematicMap.jFrameMap.getMappingToolKit(), 
							  thematicMap.getData(),
							  cd );
		} catch (TMapException e1) {
			miscUIHelper.displayErrorMessage( container, e1 );
		}
		cd.setPolygonAssociatedData( data );			
		
		jFrameThematicMap.jFrameAnnotations.setThematicMap( thematicMap );
		jFrameThematicMap.jFrameAnnotations.refreshData();
		
		jFrameThematicMap.jFrameMap.repaint();	
	}		
	
	public void setThematicMapName( File file ) {
		String name ="";
		
		if ( file != null ) {
			name =file.getAbsolutePath();
		}
		
		setThematicMapName( name );
	}
	
	private void setThematicMapName( String name ) {
		String title ="Thematic Map";
		
		if ( name != null && !"".equals( name )) {
			title+=" - " + name;
		}
		
		jFrameThematicMap.setTitle( title );
	}		
	
	public ThematicMap openThematicMapUsingArgument( String fileName  ) {
		ThematicMap thematicMap =null;

		try {
			ThematicMapDAO  thematicMapDAO = (ThematicMapDAO)DAOFactory.getInstance().get( DAOFactory.THEMATIC_MAP );
	    	thematicMap =(ThematicMap)thematicMapDAO.load( fileName );
	    	jFrameThematicMap.setThematicMap( thematicMap );
	    	setThematicMapName( thematicMap.getFile() );
	    	applyThematicMap( jFrameThematicMap );
	    	
		} catch( Exception e ) {
			e.printStackTrace();
		}
    	
    	return thematicMap;
	}
	
}
